#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QPainter>
#include<QPen>
#include<QPaintEvent>
#include<QBitmap>
#include<QPixmap>
#include<QPushButton>
#include<qmath.h>
#include<QBrush>
#include<QMouseEvent>
#include<QMessageBox>
#include <QSound>
#include<QMediaPlayer>
#include<QMenuBar>
#include<QMenu>
#include<QIcon>
#include<qtimer.h>

#include "mypushbutton.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //设置窗口标题
    this->setWindowTitle("六子棋小游戏");
    this->setFixedSize(2*MARGIN+(BOARD_GARD_SIZE-1)*BLOCK_SIZE+400,2*MARGIN+(BOARD_GARD_SIZE-1)*BLOCK_SIZE);
    this->setWindowIcon(QPixmap(":/res/logo2.jpg")); //设置应用图标
    ui->pushButton->setText("双人对战");
    ui->pushButton->setFont(QFont("微软雅黑",10,700));
    ui->pushButton->setGeometry(1000,200,200,60); //设置按钮位置和尺寸
    ui->pushButton_2->setText("人机对战");
    ui->pushButton_2->setGeometry(1000,400,200,60);
    ui->pushButton_2->setFont(QFont("微软雅黑",10,700));
    ui->pushButton_3->setText("机机对战");
    ui->pushButton_3->setGeometry(1000,600,200,60);
    ui->pushButton_3->setFont(QFont("微软雅黑",10,700));
    //设置按钮透明
    ui->pushButton->setFlat(true);
    ui->pushButton_2->setFlat(true);
    ui->pushButton_3->setFlat(true);

    banAction=true;  //默认开启禁手
    QMenuBar *menubar=menuBar();  //设置菜单栏
    QMenu *menu_1=menubar->addMenu("六子棋"); //设置菜单

    QAction *action_2=menu_1->addAction("退出游戏");
    connect(action_2,QAction::triggered,this,QMainWindow::close);  //关闭程序
    QMenu *Ban=menubar->addMenu("禁手开关");
    QAction *on=Ban->addAction("开启");
    QAction *off=Ban->addAction("关闭");

    connect(on,QAction::triggered,[=]{
        banAction = true;
    });
    connect(off,QAction::triggered,[=]{
        banAction = false;
    });
    menu_1->addSeparator();  //设置分隔线

    //此处有误，还需修改
    QSound *startsound=new QSound(":/res/backMusic.wav",this);
    startsound->play();//播放背景音乐
    startsound->setLoops(-1); //设置单曲循环

    initgame();  //默认初始化

//    this->hide();

////////////////////用图片实现返回按钮////////////
    //返回按钮
    MyPushButton * backBtn1 = new MyPushButton(":/res/backBtnFinal.png");
    backBtn1->setParent(this);
    backBtn1->move(800 , 690);


    //点击返回
    connect(backBtn1,&MyPushButton::clicked,[=](){
        //qDebug() << "点击了返回按钮";

        //播放返回按钮音效
        QSound::play(":/res/button.wav");

        //做弹起特效
        backBtn1->zoom1();
        backBtn1->zoom2();

        QTimer::singleShot(500,this,[=](){
            emit this->MainWindowBack();
        });
    });
}


MainWindow::~MainWindow()
{
    delete ui;
    if(game)   //撤销游戏指针
    {
        delete game;
        game = nullptr;
    }
    if(time1)
    {
        delete time1;
        time1=nullptr;
    }
}

//绘图事件的具体实现
void MainWindow::paintEvent(QPaintEvent *)
{
    //当鼠标移到按钮上时，按钮显示出来，其他时候透明，增加美观效果
    if(ui->pushButton->underMouse())
    {
        ui->pushButton->setFlat(false);
    }
    else
    {
        ui->pushButton->setFlat(true);
    }
    if(ui->pushButton_2->underMouse())
    {
        ui->pushButton_2->setFlat(false);
    }
    else
    {
        ui->pushButton_2->setFlat(true);
    }
    if(ui->pushButton_3->underMouse())
    {
        ui->pushButton_3->setFlat(false);
    }
    else
    {
        ui->pushButton_3->setFlat(true);
    }

    //设置背景图片
    //创建画家
    QPainter painter(this);
    painter.drawPixmap( 0 , 0 , this->width() , this->height() , QPixmap(":/res/newBackground.webp"));
    painter.setRenderHint( QPainter::Antialiasing , true); //抗锯齿,防止图像走样
    //painter.drawPixmap(950,750,250,100,QPixmap(":/res/logo"));  //画logo

    //绘制棋盘
    //1、准备操作
    QPen pen; //画笔
    pen.setWidth(2); //画笔宽度
    pen.setColor(Qt::black);
    //将画笔应用到画家
    painter.setPen(pen);
    //2、开始绘制
    for(int i=0; i < BOARD_GARD_SIZE ; i++)
    {
        //从上到下，每两根线的距离为BLOCK_SIZE,共21条线（横线）
        painter.drawLine( MARGIN , MARGIN + i * BLOCK_SIZE , MARGIN + (BOARD_GARD_SIZE - 1) * BLOCK_SIZE , MARGIN + i * BLOCK_SIZE);
        //从左到右，每两根线的距离为BLOCK_SIZE,共21条线（竖线）
        painter.drawLine( MARGIN + i * BLOCK_SIZE , MARGIN , MARGIN + i * BLOCK_SIZE , MARGIN + (BOARD_GARD_SIZE - 1) * BLOCK_SIZE);
    }

    //绘制选中点
    QBrush brush; //笔刷
    brush.setStyle(Qt::SolidPattern); //设置实心模式

    //绘制落子标记（防止鼠标出框越界）
    if(clickPosX >= 0 && clickPosX < BOARD_GARD_SIZE &&
       clickPosY >= 0 && clickPosY < BOARD_GARD_SIZE &&
       game->state==1 && game->Board[clickPosX][clickPosY] == 0)  //范围内有效，且此时正在游戏中，绘制鼠标将要落子的标记点
    {
        if(game->player) //黑棋下
        {
            brush.setColor(Qt::black); //设置黑笔
            painter.setBrush(brush); //拿出刷子
            painter.drawRect(MARGIN + BLOCK_SIZE * clickPosX - MARK_SIZE / 2, MARGIN + BLOCK_SIZE * clickPosY  - MARK_SIZE / 2, MARK_SIZE, MARK_SIZE);
        }
        else if(game->player==false&&game_type!='r')
        {
            brush.setColor(Qt::white);//设置白笔
            painter.setBrush(brush);//拿出刷子
            painter.drawRect(MARGIN + BLOCK_SIZE * clickPosX - MARK_SIZE / 2, MARGIN + BLOCK_SIZE * clickPosY  - MARK_SIZE / 2, MARK_SIZE, MARK_SIZE);
        }

    }

    //绘制棋子
    for(int i=0;i<BOARD_GARD_SIZE;i++)
    {
        for(int j=0;j<BOARD_GARD_SIZE;j++)
        {
            //要实现功能：非游戏进行时点击棋盘，不触发落子等功能
            if(game->Board[i][j]==1&&game->state==1) //游戏进行中才允许绘制棋子
           {
              brush.setColor(Qt::black);
              painter.setBrush(brush);
              painter.drawEllipse(QPoint(MARGIN + BLOCK_SIZE * i ,MARGIN + BLOCK_SIZE * j), CHESS_RADIUS , CHESS_RADIUS);
           }
            else if(game->Board[i][j]==-1&&game->state==1)
            {
                brush.setColor(Qt::white);
                painter.setBrush(brush);
                painter.drawEllipse(QPoint(MARGIN + BLOCK_SIZE * i ,MARGIN + BLOCK_SIZE * j), CHESS_RADIUS , CHESS_RADIUS);
            }
        }
    }
    update();

}


void MainWindow::initgame()   //初始化
{
        game=new GameMainFunction;
        time1=nullptr;
}


void MainWindow::init(char type)
{
    if(game)
    {
        delete game;
    }
    game=new GameMainFunction;
    game->game_type=type;
    game->state=1;

    if(time1)
    {
        delete time1;
        time1=nullptr;
    }
    clickPosX=-1;
    clickPosY=-1;
    game->startgame(type);
    update();
}

//实现对鼠标移动的监控，根据鼠标位置锁定棋盘具体位置，为下一步的落子做准备
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    //this->setMouseTracking(true);
    int x=event->x();
    int y=event->y();

    //保证鼠标在有效范围内,且棋盘边缘不落子
    if (x >= MARGIN-POS_OFFSET  &&
            x <= MARGIN+(BOARD_GARD_SIZE-1)*BLOCK_SIZE+POS_OFFSET  &&
            y >= MARGIN-POS_OFFSET  &&
            y <= MARGIN+(BOARD_GARD_SIZE-1)*BLOCK_SIZE+POS_OFFSET&&game->state==1)//保证游戏正在进行
    {
        //利用除法自动省去小数的性质来获取距离鼠标最近的左上角的点
        int col = (x - MARGIN) / BLOCK_SIZE;
        int row = (y - MARGIN) / BLOCK_SIZE;

        //在上一步的基础上加上棋盘与MAINWINDOW的距离MARGIN
        int leftTopPosX = MARGIN + BLOCK_SIZE * col;
        int leftTopPosY = MARGIN + BLOCK_SIZE * row;

        //根据距离算出合适的点击位置,一共四个点，根据两点距离选最近的
        clickPosX = -1; // 初始化
        clickPosY = -1;

        //利用len来进行取整
        int len = 0;

        //确定一个误差在范围内的点，且只可能确定一个出来
        //下面四个分别是四个方向
        len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < POS_OFFSET)  //在有效点范围内
        {
            clickPosX = col;
            clickPosY = row;
        }
        len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE) + (y - leftTopPosY) * (y - leftTopPosY));
        if (len < POS_OFFSET)  //在有效点范围内
        {
            clickPosX = col+1;
            clickPosY = row;
        }

        len = sqrt((x - leftTopPosX) * (x - leftTopPosX) + (y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
        if (len < POS_OFFSET)  //在有效点范围内
        {
            clickPosX = col;
            clickPosY = row+1;
        }
        len = sqrt((x - leftTopPosX - BLOCK_SIZE) * (x - leftTopPosX - BLOCK_SIZE) + (y - leftTopPosY - BLOCK_SIZE) * (y - leftTopPosY - BLOCK_SIZE));
        if (len < POS_OFFSET)  //在有效点范围内
        {
            clickPosX = col + 1;
            clickPosY = row + 1;
        }

    }
    // 存了坐标后更新界面
    update();

}

//实现对鼠标点击的功能完成，玩家进行点击操作后，判断轮到谁操作，并调用相关的函数 （函数仍需完善）2022.3.20
void MainWindow::mouseReleaseEvent(QMouseEvent *)
{
      if (clickPosX != -1 && clickPosY != -1&&game->state==1)
      {

          if(game_type=='s'||game->player==true)
          {

              playByPerson();  //人执行
          }
           if(game_type=='r'&&game->player==false)  //ai操作
          {

              QTimer::singleShot(AI_THINKING_TIME, this, SLOT(playByAI()));
          }
      }
      update();
}

//实现轮到人操作时，判断无误后，调用落子函数进行落子操作
void MainWindow::playByPerson()
{

    if (clickPosX != -1 && clickPosY != -1 && game->Board[clickPosX][clickPosY] == 0)
    {
        game->actionByPerson(clickPosX,clickPosY); //人进行下棋
        QSound::play(":/res/chessDown3.WAV");  //设置落子提示音
        isEnd();
        update(); //更新界面
    }
}

//实现轮到AI操作时，判断无误后，调用落子函数进行落子操作 2022.3.23
void MainWindow::playByAI()
{
    game->actionByAI(clickPosX,clickPosY);  //落子
    QSound::play(":/res/chessDown3.WAV");
    isEnd();  //判断输赢
    update();
}

//实现自动判断游戏输赢操作
void MainWindow::isEnd()
{
    if(clickPosX>=0&&clickPosX<BOARD_GARD_SIZE&&clickPosY>=0&&clickPosY<BOARD_GARD_SIZE&&game->Board[clickPosX][clickPosY]!=0) //判断游戏输赢
    {
        if(game->Board[clickPosX][clickPosY]==1&&banAction&&game->isBanAction(clickPosX,clickPosY)&&game->state==1)  //判断黑棋落子是否禁手
        {
            if(time1)
            {
                time1->stop();
                time1=nullptr;   //关闭定时器
            }
            QSound::play(":/res/lose.wav");
            QMessageBox::StandardButton standar=QMessageBox::information(this,"游戏结束！","禁手！ White-player win！\n 点击Ok返回主界面！",QMessageBox::Ok);
            if(standar==QMessageBox::Ok)
            {
                game->state=0;
                game->clear();
                ui->pushButton->setText("双人对战");
                ui->pushButton_2->setText("人机对战");
                ui->pushButton_3->setText("机机对战");
            }
        }
        else if(game->isWin(clickPosX,clickPosY)==true&&game->state==1)  //弹出提示框
        {
            if(time1)
            {
                time1->stop();
                time1=nullptr;   //关闭定时器
            }
            QSound::play(":/res/win.wav");  //获胜提示音
            QString string;
            if(game->Board[clickPosX][clickPosY]==1)
            {
                string=""
                       "恭喜黑棋选手获得胜利";   //黑棋胜
            }
            else
            {
                string="恭喜白棋选手获得胜利!";  //白棋胜
            }
            QMessageBox::StandardButton standarbutton=QMessageBox::information(this," 游戏结束啦！",string+"\n"+"点击OK再来一局",QMessageBox::Ok);
            if(standarbutton==QMessageBox::Ok)
            {
                game->state=0;
                game->clear();
                ui->pushButton->setText("双人对战");
                ui->pushButton_2->setText("人机对战");
                ui->pushButton_3->setText("机机对战");
            }
        }
        else if(game->isPeace()&&game->state==1)
        {
            if(time1)
            {
                time1->stop();
                time1=nullptr;   //关闭定时器
            }
            game->state=0;
            QMessageBox::StandardButton standarbutton=QMessageBox::information(this,"游戏结束！","该局和棋啦！\n 点击Ok返回主界面",QMessageBox::Ok);
            if(standarbutton==QMessageBox::Ok)
            {
                game->state=0;
                game->clear();
                ui->pushButton->setText("双人对战");
                ui->pushButton_2->setText("人机对战");
                ui->pushButton_3->setText("机机对战");
            }
        }
    }
}


void MainWindow::flag()
{
    game->playAIAI(clickPosX,clickPosY);
    QSound::play(":/res/chessDown3.WAV");
    isEnd();
}


void MainWindow::start_EVE()
{
    time1=new QTimer(this);   //设置定时器
    connect(time1,SIGNAL(timeout()),this,SLOT(flag()));   //连接槽函数
    time1->start(AI_THINKING_TIME);   //设置ai思考时间
}

//第一个按钮（双人对战）
void MainWindow::on_pushButton_clicked()
{
    QSound::play(":/res/button.wav");  //声效
    if(time1)
    {
        time1->stop();
        delete time1;
        time1=nullptr;     //关闭定时器
    }
     ui->centralWidget->setMouseTracking(true); //激活鼠标追踪
     setMouseTracking(true);  //激活整个窗体的鼠标追踪
     ui->pushButton->setMouseTracking(true); //进入某个按钮时，鼠标追踪属性失效，因此我们也需要激活该按钮的鼠标追踪功能
     game_type='s';  //双人模式类型
     init(game_type);  //初始化
     //设置按钮字体
     ui->pushButton->setText("重新开始:双人对战");
     ui->pushButton_2->setText("人机对战");
     ui->pushButton_3->setText("机机对战");
     update();
}

//第二个按钮（人机对战）
void MainWindow::on_pushButton_2_clicked()
{
    QSound::play(":/res/button.wav");  //声效
    if(time1)
    {
        time1->stop();
        delete time1;
        time1=nullptr;   //关闭定时器
    }
    ui->centralWidget->setMouseTracking(true); //激活鼠标追踪
    this->setMouseTracking(true);  //激活整个窗体的鼠标追踪
    ui->pushButton_2->setMouseTracking(true); //进入某个按钮时，鼠标追踪属性失效，因此我们也需要激活该按钮的鼠标追踪功能
    game_type='r';

    init(game_type);
    //设置按钮字体
    ui->pushButton->setText("双人对战");
    ui->pushButton_2->setText("重新开始：人机对战");
    ui->pushButton_3->setText("机机对战");
    update();
}

//第三个按钮（机机对战）
void MainWindow::on_pushButton_3_clicked()
{
    QSound::play(":/res/button.wav");  //声效
    this->setMouseTracking(false);  //关闭鼠标追踪
    //设置按钮字体
    ui->pushButton->setText("双人对战");
    ui->pushButton_2->setText("人机对战");
    ui->pushButton_3->setText("重新开始：机机对战");
    game_type='j'; //机机对战
    init(game_type);
    srand((unsigned)time(nullptr));
    //电脑首次落子尽量落在棋盘中间区域
    clickPosX=BOARD_GARD_SIZE/2+rand()%4;
    clickPosY=BOARD_GARD_SIZE/2+rand()%4;
    game->Board[clickPosX][clickPosY]=1;
    QSound::play(":/res/chessDown3.WAV");
    game->player=!game->player;
    start_EVE();//开始下棋
    update();
}
